import Foundation
import CoreLocation
import SystemConfiguration.CaptiveNetwork
import Network

class WifiInfoViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
    @Published var ssid: String = ""
    @Published var localIPAddress: String = ""
    @Published var externalIPAddress: String = ""
    @Published var networkStatus: String = ""

    private var locationManager: CLLocationManager?

    override init() {
        super.init()
        requestLocationPermission()
        fetchSSIDInfo()
        fetchLocalIPAddress()
        fetchExternalIPAddress()
        startNetworkMonitor()
    }

    private func requestLocationPermission() {
        locationManager = CLLocationManager()
        locationManager?.delegate = self
        locationManager?.requestWhenInUseAuthorization()
    }

    private func fetchSSIDInfo() {
        if CLLocationManager.authorizationStatus() == .authorizedWhenInUse || CLLocationManager.authorizationStatus() == .authorizedAlways {
            if let interfaces = CNCopySupportedInterfaces() as? [String] {
                for interface in interfaces {
                    if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as CFString) as NSDictionary? {
                        DispatchQueue.main.async {
                            self.ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String ?? "Unknown"
                        }
                    }
                }
            } else {
                DispatchQueue.main.async {
                    self.ssid = "Unknown"
                }
            }
        } else {
            DispatchQueue.main.async {
                self.ssid = "Location permission required"
            }
        }
    }

    private func fetchLocalIPAddress() {
        
        var address: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>?
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while ptr != nil {
                defer { ptr = ptr?.pointee.ifa_next }
                
                let interface = ptr?.pointee
                let addrFamily = interface?.ifa_addr.pointee.sa_family
                if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6),
                   let cString = interface?.ifa_name,
                   String(cString: cString) == "en0" {
                    
                    var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                    getnameinfo(interface!.ifa_addr, socklen_t(interface!.ifa_addr.pointee.sa_len),
                                &hostname, socklen_t(hostname.count),
                                nil, socklen_t(0), NI_NUMERICHOST)
                    address = String(cString: hostname)
                }
            }
            freeifaddrs(ifaddr)
        }
     
        
       
        DispatchQueue.main.async {
            self.localIPAddress = address ?? "Unknown"
        }
    }

    private func getAddressString(for interface: ifaddrs) -> String? {
        guard let sockaddr = interface.ifa_addr.pointee as? sockaddr_in else { return nil }
        var address = sockaddr.sin_addr
        var addressString = [CChar](repeating: 0, count: Int(INET_ADDRSTRLEN))

        if inet_ntop(AF_INET, &address, &addressString, UInt32(addressString.count)) != nil {
            return String(cString: addressString)
        }

        return nil
    }

    private func fetchExternalIPAddress() {
        let url = URL(string: "https://api.ipify.org?format=json")!
        let task = URLSession.shared.dataTask(with: url) { data, _, error in
            guard let data = data, error == nil else {
                DispatchQueue.main.async {
                    self.externalIPAddress = "Unknown"
                }
                return
            }

            if let json = try? JSONSerialization.jsonObject(with: data, options: []),
               let dict = json as? [String: String],
               let ip = dict["ip"] {
                DispatchQueue.main.async {
                    self.externalIPAddress = ip
                }
            } else {
                DispatchQueue.main.async {
                    self.externalIPAddress = "Unknown"
                }
            }
        }
        task.resume()
    }

    private func startNetworkMonitor() {
        let monitor = NWPathMonitor()
        monitor.pathUpdateHandler = { path in
            if path.usesInterfaceType(.wifi) {
                DispatchQueue.main.async {
                    self.networkStatus = "Connected via Wi-Fi"
                }
            } else if path.usesInterfaceType(.cellular) {
                DispatchQueue.main.async {
                    self.networkStatus = "Connected via Cellular"
                }
            } else {
                DispatchQueue.main.async {
                    self.networkStatus = "Disconnected"
                }
            }
        }

        let queue = DispatchQueue(label: "NetworkMonitor")
        monitor.start(queue: queue)
    }

    // CLLocationManagerDelegate Method
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .authorizedWhenInUse || status == .authorizedAlways {
            fetchSSIDInfo()
        } else {
            DispatchQueue.main.async {
                self.ssid = "Location permission required"
            }
        }
    }
}
